package com.drawu.drawuspring.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.drawu.drawuspring.constants.BehaviorConstants;
import com.drawu.drawuspring.constants.JwtClaimsConstant;
import com.drawu.drawuspring.domain.DTO.*;
import com.drawu.drawuspring.domain.Result;
import com.drawu.drawuspring.domain.VO.*;
import com.drawu.drawuspring.domain.po.*;

import com.drawu.drawuspring.enums.AppHttpCodeEnum;
import com.drawu.drawuspring.mapper.ForumMapper;
import com.drawu.drawuspring.mapper.MessageMapper;
import com.drawu.drawuspring.service.*;
import com.drawu.drawuspring.utils.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.stream.Collectors;

import static com.drawu.drawuspring.utils.Coze.runWorkflow;


@Service
@Slf4j
@RequiredArgsConstructor
public class ForumServiceImpl extends ServiceImpl<ForumMapper, Posts> implements IForumService {


    public final ICommentsService commentsService;
    public final IImagesService iImagesService;

    private final StringRedisTemplate redisTemplate ;

    private final IUsersService usersService ;
    private final MessageMapper messageMapper ;
    private final ICollectRecordService collectRecordService;

    private final JwtProperties jwtProperties;


    /**
     * 获取帖子列表
     */
    public PageDTO<PostVO> getAllPosts (PostPageDto postPageDto) {
        Page<Posts> page = lambdaQuery().eq(postPageDto.getArea() != null, Posts::getArea, postPageDto.getArea()).orderByDesc(Posts::getCreateTime).eq(postPageDto.getUserId()!=null, Posts::getUserId, postPageDto.getUserId()).page(postPageDto.toMpPage());
        List<Posts> records = page.getRecords();
        if (CollUtils.isEmpty(records)) {
            return PageDTO.empty(page);
        }
        List<PostVO> postVOList = BeanUtils.copyList(records, PostVO.class);
        List<Integer> ids = records.stream().map(Posts::getId).filter(Objects::nonNull).collect(Collectors.toList());
        new QueryWrapper<>();
        List<Images> images = iImagesService.list(new QueryWrapper<Images>().in("posts_id", ids));

        Map<Integer, List<Images>> imagesMap = images.stream().collect(Collectors.groupingBy(Images::getPostsId));
        Set<Integer> userIds = records.stream().map(Posts::getUserId).filter(Objects::nonNull).collect(Collectors.toSet());
        List<UserVO> usersList =BeanUtils.copyList(usersService.listByIds(userIds), UserVO.class);
        Map<Integer, UserVO> usersMap = usersList.stream().collect(Collectors.toMap(UserVO::getId, users -> users));
        for (PostVO postVO : postVOList) {
            postVO.setImages(imagesMap.get(postVO.getId()));
            postVO.setUserVO(usersMap.get(postVO.getUserId()));
            postVO.setComments(commentsService.getCommentCountByPostId(postVO.getId()));
            if (postPageDto.getUserId() != null) {
                boolean isLiked = Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(BehaviorConstants.LIKE_BEHAVIOR +postVO.getId(), postPageDto.getUserId().toString()));
                postVO.setLiked(isLiked);
                //查询当前用户是否收藏BehaviorConstants.COLLECTION_BEHAVIOR + dto.getPostsId();
                boolean isCollected = Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(BehaviorConstants.COLLECTION_BEHAVIOR + postVO.getId(),postPageDto.getUserId().toString()));
                postVO.setCollected(isCollected);
            }
        }

        return Result.success(PageDTO.of(page, postVOList)).getData();
    }

    /**
     * 获取帖子详情
     */
    public PostVO getPostDetail(Integer id) {
        //检验参数
        if (id == null) {
            return null;
        }
        Posts posts = getById(id);
        PostVO postVO = BeanUtils.copyBean(posts, PostVO.class);
        List<Images> images = iImagesService.list(new QueryWrapper<Images>().eq("posts_id", id));
        postVO.setImages(images);
        Users user = AppThreadLocalUtil.getUser();
        Users users = usersService.getById(posts.getUserId());
        UserVO authorVO = BeanUtils.copyBean(users, UserVO.class);
        UserVO userVO = BeanUtils.copyBean(user, UserVO.class);
        // currentUser是否关注author
        boolean isFocus = Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(BehaviorConstants.FOCUS_BEHAVIOR + authorVO.getId().toString(), userVO.getId().toString()));
        authorVO.setIsFocus(isFocus);
        postVO.setUserVO(authorVO);
        //查询当前用户是否点赞BehaviorConstants.LIKE_BEHAVIOR + dto.getPostsId();
        boolean isLiked = Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(BehaviorConstants.LIKE_BEHAVIOR + id, userVO.getId().toString()));
        postVO.setLiked(isLiked);
        //查询当前用户是否收藏BehaviorConstants.COLLECTION_BEHAVIOR + dto.getPostsId();
        boolean isCollected = Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(BehaviorConstants.COLLECTION_BEHAVIOR + id, userVO.getId().toString()));
        postVO.setCollected(isCollected);
        postVO.setComments(commentsService.getCommentCountByPostId(postVO.getId()));
        //查询评论
        return postVO;
    }

    public List<PostVO> getAllCollect() {
        Users user = AppThreadLocalUtil.getUser();
        // 查询Redis中收藏的帖子ID
        List<Integer> collectIds = new ArrayList<>();
        // 获取所有的 key
        Set<String> allKeys = redisTemplate.keys( BehaviorConstants.COLLECTION_BEHAVIOR + "*");
        log.info("allKeys:{}",allKeys);
        if (allKeys != null) {
            for (String key : allKeys) {
                // 获取当前 key 对应的 value
                try {
                    Boolean isMember = redisTemplate.opsForSet().isMember(key, user.getId().toString());
                    if (isMember) {
                        Integer collectId = Integer.parseInt(key.split("-")[2]);
                        collectIds.add(collectId);
                        log.info("collectId:{}",collectId);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            log.info("collectIds:{}",collectIds);
        }

       List<Posts> records = listByIds(collectIds);
        if (CollUtils.isEmpty(records)) {
            return null;
        }
        List<PostVO> postVOList = BeanUtils.copyList(records, PostVO.class);
        new QueryWrapper<>();
        List<Images> images = iImagesService.list(new QueryWrapper<Images>().in("posts_id", collectIds));

        Map<Integer, List<Images>> imagesMap = images.stream().collect(Collectors.groupingBy(Images::getPostsId));
        Set<Integer> userIds = records.stream().map(Posts::getUserId).filter(Objects::nonNull).collect(Collectors.toSet());
        List<UserVO> usersList =BeanUtils.copyList(usersService.listByIds(userIds), UserVO.class);
        Map<Integer, UserVO> usersMap = usersList.stream().collect(Collectors.toMap(UserVO::getId, users -> users));
        for (PostVO postVO : postVOList) {
            postVO.setImages(imagesMap.get(postVO.getId()));
            postVO.setUserVO(usersMap.get(postVO.getUserId()));
            postVO.setComments(commentsService.getCommentCountByPostId(postVO.getId()));
            if (user.getId() != null) {
                boolean isLiked = Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(BehaviorConstants.LIKE_BEHAVIOR +postVO.getId(), user.getId() .toString()));
                postVO.setLiked(isLiked);
                //查询当前用户是否收藏BehaviorConstants.COLLECTION_BEHAVIOR + dto.getPostsId();
                boolean isCollected = Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(BehaviorConstants.COLLECTION_BEHAVIOR + postVO.getId(),user.getId() .toString()));
                postVO.setCollected(isCollected);
            }
        }

        return postVOList;
    }

    @Override
    public PostDTO chat(PostDTO postDTO) throws Exception {
        JSONObject jsonObject = runWorkflow(postDTO);
        if (jsonObject == null) {
            return null;
            }
        String content = jsonObject.getString("content");
        String title = jsonObject.getString("title");
        PostDTO posts = new PostDTO();
        posts.setContent(content);
        posts.setTitle(title);
        return posts;
    }

    @Override
    public Result uploadImage(MultipartFile mpFile) {
        String url = iImagesService.uploadImage(mpFile,"posts");
        return Result.success(url);
    }

    @Override
    public Result deleteImage(DeleteImageDto deleteImageDto) {
        String url = deleteImageDto.getUrl();
        // 在数据库中删除
        if (url == null) {
           return Result.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        QueryWrapper<Images> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("url",url);
        iImagesService.remove(queryWrapper);
        // 在obs中删除
        iImagesService.deleteImage(url,"posts");
        return Result.success(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 创建帖子
     */
    @Override
    public Posts createPost(PostDTO dto) throws Exception {
        // : 校验参数
        if (dto == null) {
            return null;
        }
        Posts posts= BeanUtils.copyBean(dto, Posts.class);
        Users user = AppThreadLocalUtil.getUser();
        posts.setUserId(user.getId());
        this.save(posts);
        dto.setPostId(posts.getId());
        // : 保存图片
        if (dto.getImages()!= null) {
        iImagesService.saveImages(dto.getImages(), posts.getId());
        }
        return posts;
    }


    /**
     * 用户点赞
     *
     */
    @Override
    public Result like(LikesBehaviorDto dto) {
        // 1.基于前端的参数，判断是执行点赞还是取消点赞
        boolean success = dto.getOperation()==1 ? likes(dto) : unlike(dto);
        if (!success) {
            return Result.errorResult(AppHttpCodeEnum.DATA_EXIST);
        }
        // 3.如果执行成功，统计点赞总数
        Long likedTimes = redisTemplate.opsForSet()
                .size(BehaviorConstants.LIKE_BEHAVIOR + dto.getPostsId());
        // 4.更新数据库中的点赞数
        int likes = likedTimes.intValue();
        lambdaUpdate().set(Posts::getLikes, likes).eq(Posts::getId, dto.getPostsId()).update();
        String key = BehaviorConstants.LIKE_BEHAVIOR + BehaviorConstants.TOTAL;
        // 4.缓存点总数到Redis
        redisTemplate.opsForZSet().add(
                key,
                dto.getPostsId().toString(),
                likedTimes
        );
        return Result.okResult(AppHttpCodeEnum.SUCCESS);
//
//        // : 校验参数
//        if (dto == null || dto.getPostsId() == null) {
//            return Result.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
//        }
//        // : 查询用户是否登录
//        Users user = AppThreadLocalUtil.getUser();
//        if (user == null|| user.getId() == null) {
//            return Result.errorResult(AppHttpCodeEnum.NEED_LOGIN);
//        }
//        Posts posts = getById(dto.getPostsId());
//        // : 查询用户是否点过赞
//        if (dto.getOperation() == 0){
////            Object obj = redisTemplate.opsForValue().get(BehaviorConstants.LIKE_BEHAVIOR + dto.getPostsId() + user.getId().toString());
//            Object obj = redisTemplate.opsForValue().
//            if (obj!= null){
//                return Result.errorResult(AppHttpCodeEnum.DATA_EXIST);
//            }
//            if (posts == null || posts.getId() == null){
//                return Result.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
//            }
//            //保存点赞行为到缓存
//            redisTemplate.opsForValue().set(BehaviorConstants.LIKE_BEHAVIOR + dto.getPostsId() + user.getId().toString(),JSON.toJSONString(dto));
//            posts.setLikes(posts.getLikes() + 1);
//            likedRecordService.saveRecord(dto);
//        }else {
//            // 如果操作是取消点赞
//            // 从缓存中删除当前点赞信息
//            redisTemplate.delete(BehaviorConstants.LIKE_BEHAVIOR + dto.getPostsId() + user.getId().toString());
//            posts.setLikes(posts.getLikes()>0?posts.getLikes() - 1:posts.getLikes());
//            likedRecordService.deleteRecord(dto);
//        }
    }

    private boolean unlike(@NotNull LikesBehaviorDto dto) {
        // 1.获取用户id
        Integer userId = AppThreadLocalUtil.getUser().getId();
        // 2.获取Key
        String key = BehaviorConstants.LIKE_BEHAVIOR + dto.getPostsId();
        // 3.执行SREM命令
        Long result = redisTemplate.opsForSet().remove(key, userId.toString());
        // 4.删除点赞消息
        Posts posts = getById(dto.getPostsId());
        messageMapper.delete(new QueryWrapper<Message>().eq("user_id", userId).eq("target_id", posts.getUserId()).eq("source_id", dto.getPostsId()).eq("type", "likePost"));
        return result != null && result > 0;
    }

    private boolean likes(@NotNull LikesBehaviorDto dto) {
        // 1.获取用户id
        Integer userId = AppThreadLocalUtil.getUser().getId();
        // 2.获取Key
        String key = BehaviorConstants.LIKE_BEHAVIOR + dto.getPostsId();
        // 3.执行SADD命令
        Long result = redisTemplate.opsForSet().add(key, userId.toString());
        // 4.发送点赞消息
        Posts posts = getById(dto.getPostsId());
        MessageDto messageDto = new MessageDto();
        messageDto.setUserId(userId);
        messageDto.setTargetId(posts.getUserId());
        messageDto.setSourceId(dto.getPostsId());
        messageDto.setType("likePost");
        List<Images> urls = iImagesService.list(new QueryWrapper<Images>().in("posts_id", dto.getPostsId()));
        if (CollUtils.isEmpty(urls)) {
            messageDto.setUrl(posts.getTitle());
        } else {
            messageDto.setUrl(urls.get(0).getUrl());
        }
        Message message = BeanUtils.copyBean(messageDto, Message.class);
        // 查询是否已有重复点赞消息
        List<Message> messages = messageMapper.selectList(new QueryWrapper<Message>().eq("user_id", userId).eq("target_id", posts.getUserId()).eq("source_id", dto.getPostsId()).eq("type", "likePost"));
        if (CollUtils.isEmpty(messages)) {
            messageMapper.insert(message);
        }
        return result != null && result > 0;
    }

    //用于开发者测试
    @Override
    public String getToken() {
        Users user = AppThreadLocalUtil.getUser();
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.USER_ID,3);
        return JwtUtil.createJWT(jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), claims);
    }

    /**
     * 用户收藏
     * hui
     * @Override
    **/
    public Result collect(CollectBehaviorDto dto) {
        // 1.基于前端的参数，判断是执行收藏还是取消收藏
        boolean success = dto.getOperation()==1 ? collects(dto) : uncollect(dto);
        if (!success) {
            return Result.errorResult(AppHttpCodeEnum.DATA_EXIST);
        }
        // 3.如果执行成功，统计收藏总数
        Long collectTimes = redisTemplate.opsForSet()
                .size(BehaviorConstants.COLLECTION_BEHAVIOR + dto.getPostsId());
        // 4.更新数据库中的收藏数
        int collects = collectTimes.intValue();
        lambdaUpdate().set(Posts::getCollect, collects).eq(Posts::getId, dto.getPostsId()).update();
        String key = BehaviorConstants.COLLECTION_BEHAVIOR + BehaviorConstants.TOTAL;
        // 4.缓存点总数到Redis
        redisTemplate.opsForZSet().add(
                key,
                dto.getPostsId().toString(),
                collectTimes
        );
        return Result.okResult(AppHttpCodeEnum.SUCCESS);
    }

    private boolean uncollect(CollectBehaviorDto dto) {
        // 1.获取用户id
        Integer userId = AppThreadLocalUtil.getUser().getId();
        // 2.获取Key
        String key = BehaviorConstants.COLLECTION_BEHAVIOR + dto.getPostsId();
        // 3.执行SREM命令
        Long result = redisTemplate.opsForSet().remove(key, userId.toString());
        // 4.删除收藏记录
        collectRecordService.deleteCollectRecord(dto);
        return result != null && result > 0;
    }

    private boolean collects(CollectBehaviorDto dto) {
        // 1.获取用户id
        Integer userId = AppThreadLocalUtil.getUser().getId();
        // 2.获取Key
        String key = BehaviorConstants.COLLECTION_BEHAVIOR + dto.getPostsId();
        // 3.执行SADD命令
        Long result = redisTemplate.opsForSet().add(key, userId.toString());
        // 4.保存收藏记录
        collectRecordService.saveCollectRecord(dto);
        return result != null && result > 0;
    }

    public Result deletePost(Integer id) {
        // 先删除相关图片
        iImagesService.remove(new QueryWrapper<Images>().eq("posts_id", id));
        // 相关评论
        commentsService.remove(new QueryWrapper<Comments>().eq("post_id", id));
        // 再删除帖子
        this.removeById(id);
        return Result.success(AppHttpCodeEnum.SUCCESS);
    }

    public Result editPost(PostDTO dto) {


        // 校验参数
        if (dto == null) {
            return null;
        }
        Posts posts = BeanUtils.copyBean(dto, Posts.class);
        posts.setId(dto.getPostId());

        this.updateById(posts);

        // 保存图片，已有图片不改动，增加新上传图片
        QueryWrapper<Images> imageQueryWrapper = new QueryWrapper<Images>().eq("posts_id", dto.getPostId());
        List<Images> imagesList = iImagesService.list(imageQueryWrapper);
        List<String> urlList = imagesList.stream().map(Images::getUrl).toList();
        // 对比重复部分，只上传没出现的部分图片
        List<String> uploadUrls = new ArrayList<>();
        for (String url : dto.getImages()) {
            if (!urlList.contains(url)) {
                uploadUrls.add(url);
            }
        }

        if (uploadUrls != null) {
            iImagesService.saveImages(uploadUrls, posts.getId());
        }
        return Result.success(posts);
    }
}
